package gang.org.springframework.framework.metadata;

import gang.org.springframework.framework.core.annotation.GangMissingMergedAnnotation;

import java.lang.annotation.Annotation;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

public interface GangMergedAnnotation<A extends Annotation>
{
    GangAnnotationAttributes asAnnotationAttributes(GangAdapt... adaptations);

    Class<A> getType();

    /**
     * 1）该方法为一个泛型方法
     * 2）型参为T
     * @param factory 参数类型为函数参数
     *                {@link Function} 定义了两个型参，T,R，
     *                第一个型参T，类型为GangMergedAnnotation<?>
     *                第二个型参R，未明确类型，实际调整时明确
     * @param adaptations 枚举数组
     * */
    <T extends Map<String,Object>> T asMap(Function<GangMergedAnnotation<?>,T> factory, GangAdapt... adaptations);

    enum GangAdapt
    {
        CLASS_TO_STRING,
        ANNOTATION_TO_MAP;

        protected final boolean isIn(GangAdapt... adaptations)
        {
            for (GangAdapt adaptation : adaptations)
            {
                if (adaptation == this) {
                    return true;
                }
            }
            return false;
        }

        public static GangAdapt[] values(boolean classToString, boolean annotationsToMap)
        {
            EnumSet<GangAdapt> result = EnumSet.noneOf(GangAdapt.class);
            addIfTrue(result, GangAdapt.CLASS_TO_STRING, classToString);
            addIfTrue(result, GangAdapt.ANNOTATION_TO_MAP, annotationsToMap);
            return result.toArray(new GangAdapt[0]);
        }

        private static <T> void addIfTrue(Set<T> result, T value, boolean test)
        {
            if (test) {
                result.add(value);
            }
        }
    }

    /**
     * TODO
     * 业务意义
     * */
    static <A extends Annotation> GangMergedAnnotation<A> of(ClassLoader classLoader,
                                                             Object source,
                                                             Class<A> annotationType,
                                                             Map<String, ?> attributes){
        return GangTypeMappedAnnotation.of(classLoader,source,annotationType,attributes);
    }

    /**
     * 业务意义
     * 返回空注解实例
     * */
    static <A extends Annotation> GangMergedAnnotation<A> missing()
    {
        return GangMissingMergedAnnotation.getInstance();
    }
}
